package eliminate.view;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JPanel;


import eliminate.model.chess.ChessModel;
import eliminate.view.single.GameTimer;

@SuppressWarnings("serial")
public class ChessView extends JPanel implements Observer{
	
	public ChessView(ChessModel model) {
		this.chessModel.changeModel(model);
		init();
	}
	
	public ChessView(){
		init();
	}
	
	private void init(){
		chessModel.addObserver(this);
		this.addMouseListener(mouseAdapter);
		for(int i = 1; i <= ChessModel.NUM_CHESS; i++){
			try {
				chess_img[i] = ImageIO.read(new File(chess + i + ".png"));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		timer = new GameTimer(this);
	}

	protected void paintComponent(Graphics g) {
		g.drawImage(new ImageIcon(background_pic).getImage(), 0, 0,
				this.getWidth(), this.getHeight(), this);
		for (int i = 0; i < chessModel.getHorizontalNum(); i++) {
			for (int k = 0; k < chessModel.getVerticalNum(); k++) {
				DrawImage(g, i, k, chessModel.getValue(i, k, 0));
			}
		}
	}
	
	
	public void stop() {
		PAUSE = 1000000000;
		this.removeMouseListener(mouseAdapter);
	}
	
	public void start(){
		PAUSE = 20;
		this.addMouseListener(mouseAdapter);
	}
	
	public void restart() {
		PAUSE = 20;
		chessModel.changeModel(new ChessModel());
		this.addMouseListener(mouseAdapter);
	}

	private void DrawImage(Graphics g, int x, int y, int type) {
		if(type == 0){
			return;
		}
		g.drawImage(chess_img[type] ,
				(x - 1) * chessModel.getWidth() + chessModel.getValue(x, y, 1), 
				(y - 1) * chessModel.getHeight() + chessModel.getValue(x, y, 2),
				chessModel.getWidth(), chessModel.getHeight(), this);
	}

	public void update(Observable o, Object arg) {
		// TODO Auto-generated method stub
		repaint();
	}
	
	class ChessMotionAdapter extends MouseAdapter{
		int start_x;
		int start_y;
		
		int end_x;
		int end_y;
		
		@Override
		public void mousePressed(MouseEvent e) {
			start_x = e.getX() / chessModel.getWidth() + 1;
			start_y = e.getY() / chessModel.getHeight() + 1;
		}
		
		@Override
		public void mouseReleased(MouseEvent e) {
			end_x = e.getX() / chessModel.getWidth() + 1 - start_x;
			end_y = e.getY() / chessModel.getHeight() + 1 - start_y;
			if (Math.abs(end_x) >= Math.abs(end_y)) {
				if (end_x < 0 && start_x > 0) {
					end_x = start_x - 1;
				} else if (end_x > 0
						&& start_x < chessModel.getHorizontalNum()) {
					end_x = start_x + 1;
				} else {
					return;
				}
				end_y = start_y;
			} else {
				if (end_y < 0 && start_y > 0) {
					end_y = start_y - 1;
				} else if (end_y > 0
						&& start_y < chessModel.getVerticalNum()) {
					end_y = start_y + 1;
				} else {
					return;
				}
				end_x = start_x;
			}
			handle(start_x, start_y, end_x, end_y);
		}
	}
	
	public void swap(final int start_x, final int start_y, final int end_x, final int end_y){
		for(int i = 0; i < 3; i++){
			chessModel.setValue(start_x, start_y, 1, 
				(end_x - start_x) * chessModel.getWidth() / 3);
			chessModel.setValue(start_x, start_y, 2, 
					(end_y - start_y) * chessModel.getHeight() / 3);
			
			chessModel.setValue(end_x, end_y, 1, 
					(start_x - end_x) * chessModel.getWidth() / 3);
			chessModel.setValue(end_x, end_y, 2, 
					(start_y - end_y) * chessModel.getHeight() / 3);
			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			repaint();
		}
	}
	
	public void handle(final int start_x, final int start_y, final int end_x, final int end_y){
		Thread thread = new Thread(new Runnable(){
			@Override
			public void run() {
				swap(start_x, start_y, end_x, end_y);
				chessModel.swapColor(start_x, start_y, end_x, end_y);
				if(chessModel.canDelete(start_x, start_y) || 
						chessModel.canDelete(end_x, end_y)){
					delete();
				}
				else{
					swap(start_x, start_y, end_x, end_y);
					chessModel.swapColor(start_x, start_y, end_x, end_y);
				}
			}
		});
		thread.start();
		
	}
	
	public void delete(){
		Thread thread = new Thread(new Runnable(){
		
		@Override
		public void run() {
			if(chessModel.canDelete()){
				int num = chessModel.delete();
				timer.combo(num);
				while(!chessModel.isChangeble()) {
					while(chessModel.hasBlack()){
						for(int i = 0; i < 3; i++){
							chessModel.dropDown();
							repaint();
							try {
								Thread.sleep(PAUSE);
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
						chessModel.delete();
					}
					chessModel.delete();
					repaint();
					try {
						Thread.sleep(PAUSE);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			else{
				return;
			}
		}
		});
		thread.start();
	}

	private String background_pic = "media/image/singlePlayer/ChessBackground.jpg";
	
	private String chess = "media/image/chess/";
	private static Image[] chess_img = new Image[17];
	
	public static GameTimer timer;
	ChessModel chessModel = new ChessModel();
	private static int PAUSE = 20;
	private MouseAdapter mouseAdapter = new ChessMotionAdapter();
}
